package it.unibz.easytravel.expenses;

import java.util.Date;
import java.util.Vector;

import it.unibz.easytravel.R;
import it.unibz.easytravel.db.DebtsDbAdapter;
import it.unibz.easytravel.db.ExpensesDbAdapter;
import it.unibz.easytravel.db.PersonDbAdapter;
import it.unibz.easytravel.db.TravellersDbAdapter;
import it.unibz.easytravel.expenses.statistic.Converter;
import it.unibz.easytravel.travel.EditTravel;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.LinearLayout;
import android.widget.TextView;


public class ExpensesList extends Activity {

	private ExpensesDbAdapter mExpensesDb;
	private LinearLayout mList;
	private PersonDbAdapter mPersonDb;
	private TravellersDbAdapter mTravellerDb;
	private DebtsDbAdapter mDebtsDb;
	protected int id;
	private static int travel_id;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.expenses_bills);
		
		SharedPreferences settings = getSharedPreferences(EditTravel.PREFS_NAME, 0);
		travel_id = settings.getInt(EditTravel.TRAVEL_ID, -1);
	
	}
	
	public void onResume (){
		super.onResume();
		display();
	}
	
	void display() {
		mExpensesDb = new ExpensesDbAdapter(this);
		mExpensesDb.open();

		mPersonDb = new PersonDbAdapter(this);
		mPersonDb.open();
		mList = (LinearLayout) findViewById(R.id.LinearLayoutBillList);
		mList.removeAllViews();
		Cursor expensesCursor = mExpensesDb.getExpenses(travel_id);

		boolean empty = true;
		while (expensesCursor.moveToNext()) {

			if (expensesCursor.getInt(expensesCursor
					.getColumnIndexOrThrow("show")) != 0) {
				empty = false;
				TextView bill = new TextView(this);
				String bill_text = "";
				bill_text += "Amount: "
						+ Converter.convertToStringMerge(expensesCursor
								.getInt(expensesCursor
										.getColumnIndexOrThrow("amount")))
						+ "\n";

				bill_text += "Creditor: "
						+ mPersonDb.getName(expensesCursor
								.getInt(expensesCursor
										.getColumnIndexOrThrow("creditor")))
						+ "\n";

				bill_text += "Debtors:\n";
				String[] debtor = expensesCursor.getString(
						expensesCursor.getColumnIndexOrThrow("debtors")).split(
						",");
				for (int i = 0; i < debtor.length; i++) {
					bill_text += "     "
							+ mPersonDb.getName(Integer.parseInt(debtor[i])) + "\n";
				}

				bill_text += "Comment: "
						+ expensesCursor.getString(expensesCursor
								.getColumnIndexOrThrow("comment")) + "\n";
				bill.setText(bill_text + "\n");

				id = expensesCursor.getInt(expensesCursor
						.getColumnIndexOrThrow("_id"));
				bill.setId(id);

				// create listener with specific id that will be passed later on
				bill.setOnClickListener(new mClickedExpenseListener(id, this));

				mList.addView(bill);
			}
		}

		if (empty) {
			TextView text = new TextView(this);
			text.setText("No expenses were made.");
			mList.addView(text);
		}
		
		mExpensesDb.close();
		mPersonDb.close();
	}
	
	
	
	private Expense getExpense(int travel_id, int expense_id) {
		// get expense
		mExpensesDb = new ExpensesDbAdapter(this);
		mExpensesDb.open();
		Cursor expensesCursor = mExpensesDb.getExpense(travel_id, expense_id);
		expensesCursor.moveToNext();
		// get expense info
		int amount = expensesCursor.getInt(expensesCursor
				.getColumnIndexOrThrow("amount"));
		int creditor = expensesCursor.getInt(expensesCursor
				.getColumnIndexOrThrow("creditor"));
		Vector debtors = new Vector();
		String[] debtor = expensesCursor.getString(
				expensesCursor.getColumnIndexOrThrow("debtors")).split(",");
		for (int i = 0; i < debtor.length; i++) {
			debtors.addElement(Integer.parseInt(debtor[i]));
		}
		String descrition = expensesCursor.getString(expensesCursor
				.getColumnIndexOrThrow("comment"));
		mExpensesDb.close();
		return new Expense(expense_id, amount, creditor, debtors, descrition);
	}

	/**
	 * @param travel_id
	 * @param expense_id
	 * @return
	 */
	public boolean deleteAmountsSpentForExpense(int travel_id, int expense_id) {
		Expense expense = getExpense(travel_id, expense_id);
		Vector debtors = expense.getDebtorsIds();
		int creditor = expense.getCreditorsId();
		int amnt = -expense.getAmount(); // Negative value

		mTravellerDb = new TravellersDbAdapter(this);
		mTravellerDb.open();

		boolean debtor_himself = false;
		int nrOfDebtorsSize = debtors.size();
		int debt_per_person = amnt / nrOfDebtorsSize;

		for (int i = 0; i < nrOfDebtorsSize; i++) {
			int debtor = ((Integer) debtors.elementAt(i)).intValue();
			// if creditor is not crediting himself
			if (creditor != debtor) {
				// This step is computed for all debtors
				mTravellerDb
						.addToMoneyFlow(debtor, travel_id, -debt_per_person);
			} else {
				// Creditor is in the debtors list
				debtor_himself = true;
				mTravellerDb.addToMoneyFlow(creditor, travel_id, amnt
						- debt_per_person);
			}
		}

		// covers the case when creditor is not in debtors list
		if (!debtor_himself)
			mTravellerDb.addToMoneyFlow(creditor, travel_id, amnt);

		mTravellerDb.close();

		return true;
	}

	/**
	 * 
	 * @param travel_id
	 * @param expense_id
	 * @return
	 */
	public boolean deleteDebtsFromExpense(int travel_id, int expense_id) {
		Expense expense = getExpense(travel_id, expense_id);
		mDebtsDb = new DebtsDbAdapter(this);
		mDebtsDb.open();

		Vector debtors = expense.getDebtorsIds();
		int creditor = expense.getCreditorsId();
		int amnt = -expense.getAmount(); // Negative value

		int nrOfDebtorsSize = debtors.size();
		int total_debt_per_person = amnt / nrOfDebtorsSize;

		int cursor_id = -1;

		for (int i = 0; i < nrOfDebtorsSize; i++) {
			
			int debtor = ((Integer) debtors.elementAt(i)).intValue();
			// if not himself
			if (creditor != debtor) {
				boolean exist = false;
				int debt_per_person = total_debt_per_person;

				// if relation already exists
				cursor_id = mDebtsDb.getDebtRelationID(travel_id, creditor,	debtor);
				if (cursor_id > 0) {
					exist = true;
					
					int delta = mDebtsDb.getAmountSpent(cursor_id)+ debt_per_person;
					if(delta < 0 ){
						mDebtsDb.deleteNode(cursor_id);
						mDebtsDb.createDebt(travel_id, -delta, debtor, creditor);
					}
					if(delta == 0 ){mDebtsDb.deleteNode(cursor_id);}
					if(delta > 0 ){mDebtsDb.addToDebtRelation(cursor_id, debt_per_person);}
				}else{

				// if reverse relation exists
				cursor_id = mDebtsDb.getDebtRelationID(travel_id, debtor, creditor);
				if (cursor_id > 0) {
					exist = true;
					mDebtsDb.addToDebtRelation(cursor_id, -debt_per_person);
					
				}}

				// if relation does is not in DB
				if (!exist)	mDebtsDb.createDebt(travel_id, -debt_per_person, debtor, creditor);
			}

		}
		mDebtsDb.open();

		return true;
	}

	/**
	 * 
	 * @param travel_id
	 * @param expense_id
	 * @return
	 */
	public boolean cancelExpense(int travel_id, int expense_id) {
		Expense expense = getExpense(travel_id, expense_id);
		Date date = new Date();
		Vector debtors = expense.getDebtorsIds();
		int creditor = expense.getCreditorsId();
		int amount = expense.getAmount(); // Negative value
		String comment = expense.getDescription();

		mExpensesDb = new ExpensesDbAdapter(this);
		mExpensesDb.open();
		mExpensesDb.setInvisible(travel_id, expense_id);
		mExpensesDb.createExpense(travel_id, -amount, creditor, debtors,
				comment, false, false, date);

		mExpensesDb.close();
		return true;
	}

	private static class mClickedExpenseListener implements OnClickListener {

		private int id;
		private Activity activity;

		public mClickedExpenseListener(int id, Activity activity) {
			this.id = id;
			this.activity = activity;
		}

		public void onClick(View v) {
			Log.i("on_click_bill_id", id + "");
			activity.showDialog(id);
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		final int bill_id = id;
		String[] operation = { "cancel debt", "add new expense" };
		return new AlertDialog.Builder(ExpensesList.this).setTitle("Operation")
				.setItems(operation, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						// cancel expense
						if (which == 0) {
							Log.i("inside_on_click_bill_id", bill_id + "");
							// Must find expense and mark as canceled and create
							// new one that is negative to the one that is
							// canceled
							if (deleteAmountsSpentForExpense(travel_id, bill_id)
									& deleteDebtsFromExpense(travel_id, bill_id)
									& cancelExpense(travel_id, bill_id)) {
								new AlertDialog.Builder(ExpensesList.this)
								.setTitle("Operation Sucessful!")
								.setPositiveButton("OK", new DialogInterface.OnClickListener(){ 
							          public void onClick(DialogInterface dialog, int which) {
							        	  display();
							          }
							          }) 
							          .create()
							          .show();
							} else {
								new AlertDialog.Builder(ExpensesList.this)
								.setTitle("Could not cancel!")
								.setPositiveButton("OK", new DialogInterface.OnClickListener(){ 
							          public void onClick(DialogInterface dialog, int which) {
							        	  display();
							          }
							          }) 
							          .create()
							          .show();
							}
						}

						// add new expense
						if (which == 1) {
							Intent intent = new Intent(ExpensesList.this,
									AddExpense.class);
							startActivity(intent);
						}

					}
				}).create();
	}
}
